// Input / output interface
//--------------------------------
#ifndef IO_H
#define IO_H
#include "common.h"
#include <boost/multi_array.hpp>

#define INPUT_QUIT       256
#define INPUT_CONFIRM    257
#define INPUT_CANCEL     258
#define INPUT_UPARROW    259
#define INPUT_DOWNARROW  260
#define INPUT_LEFTARROW  261
#define INPUT_RIGHTARROW 262
#define INPUT_PGUP       263
#define INPUT_PGDN       264
#define INPUT_HOME       265
#define INPUT_END        266
#define INPUT_BACKSPACE  267

class IO {
public:

    static const uint LAYERS = 8;

    IO();
    virtual ~IO();

    void Init( const std::string& title, uint width, uint height );
    void Destroy();
    virtual void SetTitle( const std::string& title ) = 0;

    typedef std::pair< uint, uint > Coord;
    typedef std::set< Coord >       CoordSet;
    void ShowCursor( uint x, uint y );
    void ShowCursor( const CoordSet& set );
    void HideCursor();

    void Clear( uint layer );
    void Clear();
    virtual void Render( char animation ) = 0;

    typedef std::pair< uchar, Colour > Sym;
    typedef std::vector< Sym >         SymList;

    // Draw character
    virtual void Draw( uchar ch,                const Colour& c, uint x, uint y, uint layer );
    // Draw animated character
    virtual void Draw( const SymList& ch,                        uint x, uint y, uint layer );
    // Draw several characters
    virtual void Draw( const     ustring& text, const Colour& c, uint x, uint y, uint layer );
    virtual void Draw( const std::string& text, const Colour& c, uint x, uint y, uint layer );
    // Draw background
    virtual void Draw(                          const Colour& c, uint x, uint y, uint layer );

    virtual uint Input() = 0;

protected:

    typedef SymList Data;
    typedef boost::multi_array< Data, 3 > DataArray;
    DataArray* _data;
    typedef boost::multi_array< Colour, 3 > BGArray;
    BGArray* _bg;

    uint _width;
    uint _height;

    CoordSet _coordSet;

private:

    virtual void InitInternal() = 0;
    virtual void DestroyInternal() = 0;

};

#endif
